/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package miselania.memoriaintermedia;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;


/**
 *
 * Representa una abstraccion de 
 * un gestor de memoria intermedia
 */
public class GestorMemoria_Intermedia {
    
    static final Logger logger= Logger.getLogger("Gestion de buffer");
    
    //representa los bloques de  la memoria intermedia o buffery las reserva
    private Pagina[] buffer;  //como una rreglo de bits
    //numero de paginas en total en el buffer
    private  int numeroPagina;
    //posicion en el buffer de la ultima pagina colocada
    private int posicionUltimaPagina=-1;
    //cola para el control de sustitucion basada en LRU
    private Queue colaLRU;
    
    
    /*
     * crea un nuevo Gestor de memoria intermedia
     */

    public GestorMemoria_Intermedia(int numeroPaginas) {
        this.numeroPagina = numeroPaginas;
        
        //crear el buffer con paginas vacias
        buffer=new Pagina[numeroPaginas];
        //crea una cola FIFO
        colaLRU= new LinkedList<Integer>();
        
    }
    
    /*
     * Devuelve una pagina conociendo el numero de paginas
     * 
     */
    public Pagina recuperarPaginaDelBuffer(int numeroPagina){
        
        //verifcar si la posicion esta ya en buffer
        int posicion=posicionDePaginaEnBuffer(numeroPagina);
        if(posicion >= 0) //la pagina esta en al buffer
        {
            //marcar pagina o bloque como recientemente referenciada
            colaLRU.remove(numeroPagina);//eliminar de su posicion anterior para ponerlo al final de la cola
            colaLRU.add(numeroPagina); ///como indicador de ser el ultimo  usado
            //devolver la pagina del buffer al solicitante
            return buffer[posicion];
        }
        return null;
    }
    
    /*
     * poner una pagina en el buffer de la memoria intermedia
     * recibe la pagina
     * y retorna la pagina k sera descartada si el buffer esta ocuapdo
     * 
     */
    public Pagina ponerPaginaEnBuffer(Pagina pagina){
        //si la pagina esta en el buffer
        if(estaPaginaEnBuffer(pagina)){
            //no descartar ninguna pagina
            return null;
        }//si la pagina esta en el buffer pero con espacio en el buffer
        else if(!bufferLleno()){
            //asignar la nueva pagina el bloque o pagina libre
            posicionUltimaPagina++;
            buffer[posicionUltimaPagina]=pagina;
            //actualizar la LRU
            colaLRU.remove(posicionUltimaPagina);
            colaLRU.add(posicionUltimaPagina);
            return null;
        }//si la pgina no esta en el buffer , pero sin espacion en la memoria intermedia
        else
        {
            //recuperar la pagin a eliminar
            
            //identificar el id de pagina a descartar de la colaLRU
            int numeroPaginaDescartada=(Integer) colaLRU.remove(); 
            //conocer el id de pagina ubicar la posicion 
            //de la pagina en el buffer
            int posicion= posicionDePaginaEnBuffer(numeroPaginaDescartada);
            
              //extraer pagina a descartar del buffer
            Pagina paginaDescartada= buffer[posicion];
          
            //actualizar la nueva pagina enla posicion de la 
            //pagina descartada
            buffer[posicion]=pagina;
            //hacer que el id de la nueva pagina sea el mas recientemente referenciado
            colaLRU.add(pagina.getNumeroPagina());
            
            return  paginaDescartada;
            
        }
    }
        
        private int posicionDePaginaEnBuffer(int numeroPagina){
            int posicion=-1;
            for (int i = 0; i < buffer.length; i++) {
                if((buffer[i] != null ) && (numeroPagina==buffer[i].getNumeroPagina()))
                {
                    posicion=i;
                    break;
                }
            }
            return posicion;
        }
    
        private boolean estaPaginaEnBuffer(Pagina pagina){
            return (posicionDePaginaEnBuffer(pagina.getNumeroPagina()) != -1);
        }
    
        private boolean bufferLleno(){
            return numeroPagina-1==posicionUltimaPagina;
        }
        
        @Override
        public String toString()
        {
            String resultado="";
            for (int i = 0; i < buffer.length; i++) {
                resultado +="Pagina[" +i+ "]:"+ buffer[i]+"\n";
            }
            return resultado +"\n" + this.colaLRU;
        }
        
        public static void main(String[] args){
            
            
            //crear el gesto de memoria
            GestorMemoria_Intermedia gestorbuffer= new GestorMemoria_Intermedia(6);
            //paginas del disco
            System.out.println("Paginas del disco: ");
            Pagina[] paginas = new Pagina[10];
            for (int i = 0; i < paginas.length; i++) {
                Pagina pagina= new Pagina(i, "p"+i);
                paginas[i]=pagina;
                System.out.println(pagina);
            }
            System.out.println("contenido del gestor");
            System.out.println(gestorbuffer);
            for (int i = 0; i < paginas.length; i++) {
                gestorbuffer.ponerPaginaEnBuffer(paginas[i]);
            }
            System.out.println("contenido del gestor despues de poner bloques");
            System.out.println(gestorbuffer);
            
            System.out.println("poner una pagina en el buffer :");
            Pagina paginaN= new Pagina(10, "p10");
            Pagina paginaE = gestorbuffer.ponerPaginaEnBuffer(paginaN);
            System.out.println(paginaE);
            System.out.println(gestorbuffer);
            
            
            System.out.println("recuperar la pagina del buffer:");
            Pagina pagina1= gestorbuffer.recuperarPaginaDelBuffer(7);
            System.out.println(pagina1);
            System.out.println(gestorbuffer);
            
            System.out.println("recuperar otra pagina del buffer :");//una q no este en la cola
            Pagina pagina2= gestorbuffer.recuperarPaginaDelBuffer(3);
            System.out.println(pagina2);
            System.out.println(gestorbuffer);
        }
        
        
        
    
}
